/*
 * GameMessage - Container for gameplay inputs.
 *
 * Copyright 2008 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package rules;

class GameMessage
{

	inline public static var msg_placetower = 0;
		// [x,y, dryrun]
	inline public static var msg_placeline = 1;
		// [x,y, dryrun]
	inline public static var msg_upgradetower = 2;
	inline public static var msg_selecttarget = 3;
	inline public static var msg_selecttower = 4;
	inline public static var msg_runsim = 5;

	public var style : Int;
	public var message : Dynamic;

	public function new(style : Int, message : Dynamic)
	{
		this.style = style;
		this.message = message;
	}
	
	public function _parse()
	{
		// parse should only be run by RulesAPI.message
		// this allows the gameplay responses to aggregate;
		// thrown errors can be handled by the client seperately 

		switch(style)
		{
			case(msg_placetower):
				placetower(message);
			case(msg_placeline):
				placeline(message);
			case(msg_selecttower):
				selecttower(message);
			case(msg_selecttarget):
				selecttarget(message);
			case(msg_runsim):
				for (n in 0...message)
					runsim();
		}
		
	}

	private function placetower(message : Dynamic)
	{


		try
		{
			var x = message[0];
			var y = message[1];
			var dryrun = message[2];
			var game = RulesAPI.g;
			if (game.gameover == true)
				throw new GameResponse(GameResponse.msg_error,
				"Game Over");			
			if (game.energy+FortressData.cost_tower<0)
				throw new GameResponse(GameResponse.msg_error,
				"Not Enough Resources");						
			if (!(GameMap.inbounds(x,y)))
				throw new GameResponse(GameResponse.msg_error,
				"Out of Bounds");
			var tile = game.m.tiles[x][y];
			if (tile.terrain==GameTile.ter_space)
				throw new GameResponse(GameResponse.msg_error,
				"No Land There");
			if (!tile.fortnearby())
				throw new GameResponse(GameResponse.msg_error,
				"No Fort Nearby");
			if (tile.fort!=null)
			{
				if (tile.fort.style==FortressData.fort_line) 
					// upgrade lines
				{
				}
				else
				throw new GameResponse(GameResponse.msg_error,
				"Fortress Already Exists Here");
			}

			if (dryrun)
				throw new GameResponse(GameResponse.msg_dryconfirm,
				null);						

			if (tile.fort!=null)
			{
				tile.fort.kill();
			}
			FortressData.changeenergy(FortressData.cost_tower);
			var newfort = new FortressData(FortressData.fort_tower);
			tile.fort = newfort;
			newfort.x = x;
			newfort.y = y;
			newfort.shooter = new Shooter(newfort);
			
			Creep.killfromplacement(x,y);
		}
		catch (z : GameResponse)
		{ throw z; }
		catch (z : Dynamic)
		{
			throw new GameResponse(GameResponse.msg_error,
			"Malformed Message caused: "+Std.string(z));
		}

	}
	
	private function placeline(message : Dynamic)
	{

		try
		{
			var x = message[0];
			var y = message[1];
			var dryrun = message[2];
			var game = RulesAPI.g;
			if (game.gameover == true)
				throw new GameResponse(GameResponse.msg_error,
				"Game Over");
			var realcost = FortressData.cost_line-game.numlinesplaced;
			if (game.energy+realcost<0)
				throw new GameResponse(GameResponse.msg_error,
				"Not Enough Resources");						
			if (!(GameMap.inbounds(x,y)))
				throw new GameResponse(GameResponse.msg_error,
				"Out of Bounds");
			var tile = game.m.tiles[x][y];
			if (tile.terrain==GameTile.ter_space)
				throw new GameResponse(GameResponse.msg_error,
				"No Land There");
			if (tile.fort!=null)
				throw new GameResponse(GameResponse.msg_error,
				"Fortress Already Exists Here");						
			if (!tile.fortnearby())
				throw new GameResponse(GameResponse.msg_error,
				"No Fort Nearby");

			if (dryrun)
				throw new GameResponse(GameResponse.msg_dryconfirm,
				null);						

			FortressData.changeenergy(realcost);
			game.numlinesplaced+=1;
			var newfort = new FortressData(FortressData.fort_line);
			tile.fort = newfort;
			newfort.x = x;
			newfort.y = y;
			
			Creep.killfromplacement(x,y);
		}
		catch (z : GameResponse)
		{ throw z; }
		catch (z : Dynamic)
		{
			throw new GameResponse(GameResponse.msg_error,
			"Malformed Message caused: "+Std.string(z));
		}

	}

	private function selecttower(message : Dynamic)
	{
		try
		{
			var x = message[0];
			var y = message[1];
			var game = RulesAPI.g;
			if (game.gameover == true)
				throw new GameResponse(GameResponse.msg_error,
				"Game Over");			
			if (!(GameMap.inbounds(x,y)))
				throw new GameResponse(GameResponse.msg_error,
				"Out of Bounds");
			var tile = game.m.tiles[x][y];
			if (tile.terrain==GameTile.ter_space)
				throw new GameResponse(GameResponse.msg_error,
				"No Land There");
			if (tile.fort==null)
				throw new GameResponse(GameResponse.msg_error,
				"No tower here...");						
			if (tile.fort.shooter==null)
				throw new GameResponse(GameResponse.msg_error,
				"No tower here...");						

			game.selectedtower = tile.fort.shooter;

			GameResponse.addcomposition(
			new GameResponse(GameResponse.msg_towerselected,
				game.selectedtower));
		}
		catch (z : GameResponse)
		{ throw z; }
		catch (z : Dynamic)
		{
			throw new GameResponse(GameResponse.msg_error,
			"Malformed Message caused: "+Std.string(z));
		}

	}

	private function selecttarget(message : Dynamic)
	{
		try
		{
			RulesAPI.g.selectedtower.selecttarget(message[0],
						message[1], message[2]);
		}
		catch (z : GameResponse)
		{ throw z; }
		catch (z : Dynamic)
		{
			throw new GameResponse(GameResponse.msg_error,
			"Malformed Message caused: "+Std.string(z));
		}
		
	}
	
	private function runsim()
	{

		var game = RulesAPI.g;
		
		if (game.gameover == true)
			throw new GameResponse(GameResponse.msg_error,
			"Game Over");			

		game.framessurvived+=1;

		for (n in game.fortdatas)
			n.up();
		
		for (w in game.wavehash)
			w.up();

		for (s in game.shots)
			s.up();

		for (c in game.creeps)
			c.up();

		FortressData.changeenergy(4);
		game.timetonextwave-=1;
		
		if (game.timetonextwave<=0)
		{
			var tmpnext : Float = Game.timebetweenwaves;
			for (n in 0...game.wavenum)
			{
				tmpnext = tmpnext * 0.96;
				if (tmpnext<5) // give player a breather
					tmpnext = Game.timebetweenwaves/2;
			}
			game.timetonextwave = Std.int(tmpnext);
			Wave.nextwave();
		}
				
	}
	
}
